/*
 * Interpreter.cpp
 *
 *  Created on: 15.04.2012
 *      Author: Eugene Kornykhin
 */
#include <vector>
#include <stdexcept>
#include <iostream>
#include "PElement.h"
#include "Poliz.h"
#include "PolizPosition.h"
#include "Interpreter.h"
using namespace std;

Interpreter::Interpreter() {
}

Interpreter::~Interpreter() {
	while(!runtime.empty()) { delete runtime.top(); runtime.pop(); }
}

void Interpreter::interpret(const Poliz &p, map<string, int> initials)
{
	poliz = p;
	PolizIterator iterator(poliz, poliz.beginPosition());

	vars = initials;

	while(!runtime.empty()) { delete runtime.top(); runtime.pop(); }

	while(! (*iterator).isHalt()) {
		(*iterator).execute(*this);
		iterator.moveto((*iterator).next_position_after(iterator.getPosition()));
	}
}


int Interpreter::getVarValue(string name) const {
	if (vars.find(name) == vars.end()) {
		throw invalid_argument("Variable `" + name + "' is not defined");
	} else {
		return vars.at(name);
	}
}

void Interpreter::setVarValue(string name, int value) {
	vars[name] = value;
}

void Interpreter::pushPolizElement(const PElement &element) {
	runtime.push(element.clone(poliz));
}

const PElement &Interpreter::popPolizElement() {
	const PElement *e = runtime.top();
	runtime.pop();
	gc.add(e);
	return *e;
}


template<typename Data>
GarbageCollector<Data>::GarbageCollector()
: size(0), garbage(CAPACITY, 0)
{
}



template<typename Data>
GarbageCollector<Data>::~GarbageCollector()
{
	for(size_t i = 0; i < CAPACITY; i++) {
		delete garbage[i];
		garbage[i] = 0;
	}
}



template<typename Data>
void GarbageCollector<Data>::add(const Data *data)
{
	if (size == CAPACITY) {
		size = 0;
	}
	delete garbage[size];
	garbage[size++] = data;
}


template <typename Data>
GarbageCollector<Data>::GarbageCollector(const GarbageCollector<Data> &gc)
: size(0), garbage(CAPACITY, 0)
{

}

